/* SINTACTICO */
grammar AnaC;

options{
	k = 4;
}

@header{ package pl.equipo13.p6; }

@lexer::header{ package pl.equipo13.p6; }

@rulecath { 
 catch (RecognitionException ae) {
               System.err.println(ae.getMessage());
           throw ae;
       }
}

entrada: (bucle | funcion) EOF;
funcion: tipo_dato IDENT APARENTESIS VOID CPARENTESIS ALLAVE (instruccion)* CLLAVE;
bucle: WHILE APARENTESIS exp CPARENTESIS ALLAVE (instruccion)* CLLAVE;
instruccion: asignacion | condicional | declaracion | bucle | llamada;
cond_arit: variable OPERADORCOMPARAR variable IFARIT variable DOSPUNTOS variable; 
declaracion: tipo_dato IDENT (COMA IDENT)*  ((IGUAL) exp)? SEPARADOR;
asignacion: IDENT IGUAL ( exp | cond_arit) SEPARADOR;
llamada: IDENT APARENTESIS argumentos CPARENTESIS SEPARADOR;
argumentos: (variable | CADENA)? (COMA (variable | CADENA))*;
condicional: IF APARENTESIS exp CPARENTESIS instruccion | if_comp;
if_comp: ALLAVE (instruccion)* (BREAK SEPARADOR)? CLLAVE;

exp: (NEGADO | CAMBIOSIGNO)? exp_sr (OPERADORCOMPARAR exp_sr)?;
exp_sr: exp_mult (OPERADORSUMRES exp_mult)*;
exp_mult: exp_base (OPERADORMULDIV exp_base)*;
exp_base: variable | APARENTESIS exp_base CPARENTESIS;

variable: IDENT | NUMERO | CARACTER;

tipo_dato: VOID | INT | CHAR | FLOAT;

/* LEXICO */
WHILE : 'while';
IF : 'if';
VOID : 'void';
INT : 'int';
BREAK : 'break';
CHAR : 'char';
FLOAT : 'float';

fragment NUEVA_LINEA : ('\n' | '\r\n');
fragment LETRA : ('A'..'Z') | ('a'..'z') | ('_');
fragment DIGITO : '0'..'9';
fragment MAYOR: '>';
fragment MENOR: '<';
fragment ASTERISCO: '*';
fragment SLASH: '/';
fragment MAS: '+';
fragment GUION: '-';
fragment COMILLAS: '"';
fragment ASPERSAN: '&';
fragment BARRA: '|';
fragment COMILLASIMPLE: '\'';
NEGADO: '!';
IFARIT: '?';
CADENA: COMILLAS (options { greedy=false; }:.)* COMILLAS;
IGUAL: '=';
DOSPUNTOS: ':';
SEPARADOR: ';';
COMA: ',';
fragment MAYORIGUAL: MAYOR IGUAL;
fragment MENORIGUAL: MENOR IGUAL;
fragment AND: ASPERSAN ASPERSAN;
fragment OR: BARRA BARRA;
CAMBIOSIGNO: GUION;

BLANCO : (' '|'\t'|NUEVA_LINEA) {$channel=HIDDEN;};

APARENTESIS: '(';
CPARENTESIS: ')';
ALLAVE: '{';
CLLAVE: '}';

IDENT : LETRA(LETRA|DIGITO)*;
NUMERO : ((DIGITO)+ '.') => (DIGITO)+ '.' (DIGITO)* | (DIGITO)+;
CARACTER: COMILLASIMPLE (LETRA | DIGITO) COMILLASIMPLE;

OPERADORCOMPARAR: MAYOR | MENOR | MAYORIGUAL | MENORIGUAL | AND | OR | NEGADO;
OPERADORMULDIV: ASTERISCO | SLASH;
OPERADORSUMRES: MAS | GUION;